// SPDX-License-Identifier: GPL-2.0

/**
 * Copyright (C) 2025 Huawei Technologies Co., Ltd.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, see <https://www.gnu.org/licenses/>.
 */


/** @file cmanuapi.h
 * @brief Low-level wrappers for Kunpeng Cache Management driver interface
 *
 * The API is a thin wrapper on top of driver calls which translates driver input
 * and output into user-space errno and return codes. 
 */

#if !defined(CMAN_UAPI_H)
#define CMAN_UAPI_H

#include <stddef.h>
#include <sys/types.h>

#if defined(__cplusplus)
extern "C" {
#endif

/**
 * A define for UAPI version number
 */
#define CMANUAPI_VER 1008

extern int fd;

/**
 * Initializes cmanuapi.
 * 
 * @return 0 in case of successful initialization.
 *         -1 in case of error, errno is set accordingly (see exceptions below) in that case.
 * 
 * @exception ENODEV        Driver cannot be accessed (not loaded, not enough permissions to access driver interface etc.).
 * @exception EBUSY         Driver is already being accessed by another process.
 * @exception EMFILE        Too many file descriptors are opened for the driver device.
 * @exception EBADE         Wrong kernel-space address (fail to copy data between user- and kernel spaces, etc.).
 * @exception EBADF         Incompatibility between cmanuapi and CMAN driver versions.
 */
int cman_uapi_init(void);

/**
 * Reads value stored in L2 I/D partition register for the specified core.
 * 
 * @param  cpu   Core ID.
 * @param  dmask Pointer to variable to store data requests mask.
 * @param  imask Pointer to variable to store instructions mask.
 * @return       0 in case of successful get operation.
 *               -1 in case of error, errno is set accordingly (see exceptions below) in that case.
 * 
 * @exception EINVAL        Some of input parameters is incorrect (e.g. provided L2 I/D partition mask is out of boundaries).
 * @exception EBADE         Wrong kernel-space address (fail to copy data between user- and kernel spaces, etc.).
 * @exception ECANCELED     CPU is not online.
 * @exception EIDRM         CMAN libuapi is not initialized, but function is tried to be called.
 */
ssize_t cman_uapi_l2_partition_get(int cpu, unsigned long* dmask, unsigned long* imask);

/**
 * Writes specified mask into L2 I/D partition register for the specified core.
 * 
 * @param  cpu   Core ID. If `cpu` is equal to -1, then L2 I/D partition configuration will be applied for the whole system.
 * @param  dmask Mask to be applied for data requests.
 * @param  imask Mask to be applied for instructions.
 * @return       0 in case of successful set operation.
 *               -1 in case of error, errno is set accordingly (see exceptions below) in that case.
 * 
 * @exception EINVAL        Some of input parameters is incorrect (e.g. provided L2 I/D partition mask is out of boundaries).
 * @exception EBADE         Wrong kernel-space address (fail to copy data between user- and kernel spaces, etc.).
 * @exception EPERM         Provided L2 I/D partition mask cuts off more instructions or data than allowed by HW.
 * @exception EIO           Error during write to one of HW registers.
 * @exception ECANCELED     CPU is not online.
 * @exception EIDRM         CMAN libuapi is not initialized, but function is tried to be called.
 */
ssize_t cman_uapi_l2_partition_set(int cpu, unsigned long dmask, unsigned long imask);

/** @struct hw_info_ioctl_args
 *  @brief  Struct containing hardware-dependent information for underlying platform.
 *  @var    hw_info_ioctl_args::l2_segment_size
 *  Member 'l2_segment_size' contains size of L2 I/D partition granularity.
 *  @var    hw_info_ioctl_args::l2_capacity
 *  Member 'l2_capacity' contains L2 cache capacity of a single CPU.
 */
#pragma pack(push, 8)
typedef struct hw_info_ioctl_args {
    long long int l2_segment_size;
    unsigned long long int l2_capacity;
} hw_info_ioctl_args_t;
#pragma pack(pop)

/**
 * Retrieves hardware-dependent information for underlying platform.
 *
 * @return       Struct containing hardware-dependent information for underlying platform.
 *               Struct containing {-1, 0} in case of error,
 *               errno is set accordingly (see exceptions below) in that case.
 *
 * @exception EIDRM         CMAN libuapi is not initialized, but function is tried to be called.
 */
hw_info_ioctl_args_t cman_uapi_hw_info(void);

/**
 * Resets L2 I/D partition configuration for the specified CPU.
 *
 * @param  cpu   Core ID. If `cpu` is equal to -1, then L2 I/D partition configuration will be reset for the whole system.
 * @return       0 in case of successful reset operation.
 *               -1 in case of error, errno is set accordingly (see exceptions below) in that case.
 *
 * @exception EINVAL        Some of input parameters is incorrect (wrong cpu id).
 * @exception EBADE         Wrong kernel-space address (fail to copy data between user- and kernel spaces, etc.).
 * @exception EIO           Error during write to one of HW registers.
 * @exception ECANCELED     CPU is not online.
 * @exception EIDRM         CMAN libuapi is not initialized, but function is tried to be called.
 */
int cman_uapi_reset_l2_partition(int cpu);

#if defined(__cplusplus)
} /* extern "C" */
#endif

#endif /* CMAN_UAPI_H */
